package com.utils.basehelper.encrypt;

import java.math.BigInteger;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.Set;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
//import org.apache.commons.lang3.StringUtils;

import com.utils.basehelper.string.StringUtil;

import sun.misc.BASE64Decoder;

public class EncryptJAVAjs {


	/**
	 * 用MD5 生成唯一token
	 * 
	 * @param paramStr
	 * @return
	 */
	public static String createToken(String paramStr) {
		paramStr = paramStr + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) +"" /*InitConst.TOKEN_KEY*/;
		try {
			return createToken(paramStr, "MD5");
		} catch (Exception e) {
			return paramStr;
		}
	}

	/**
	 * 使用指定加密类型 生成token
	 * @param inStr
	 * @param type
	 * @return
	 * @throws Exception
	 */
	private static String createToken(String inStr, String type) throws Exception {
		MessageDigest md = null;
		String out = null;
		try {
			md = MessageDigest.getInstance(type);
			byte[] digest = md.digest(inStr.getBytes());
			out = byte2hex(digest);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			throw e;
		}
		return out;
	}

	/**
	 * 二进制转化为16进制
	 * @param b
	 * @return
	 */
	private static String byte2hex(byte[] b) {
		String hs = "";
		String stmp = "";
		for (int n = 0; n < b.length; n++) {
			stmp = Integer.toHexString(b[n] & 0xFF);
			if (stmp.length() == 1)
				hs = hs + "0" + stmp;
			else {
				hs = hs + stmp;
			}
		}
		return hs.toUpperCase();
	}

	/**
	 * 根据请求的关键参数，按照字典排序，拼接上uri,再用md5生成sign。MD5(/tt/api/user/getuser?id=1&times=1111)
	 * @param paramStr
	 * @return
	 */
	public static String createSign(String uri,Map<String, String> params, boolean encode) throws Exception {
		Set<String> keysSet = params.keySet();
		Object[] keys = keysSet.toArray();
		Arrays.sort(keys);
		StringBuffer temp = new StringBuffer();
		boolean first = true;
		temp.append(uri);
		temp.append("?");
		for (Object key : keys) {
			if (first) {
				first = false;
			} else {
				temp.append("&");
			}
			temp.append(key).append("=");
			Object value = params.get(key);
			String valueString = "";
			if (null != value) {
				valueString = String.valueOf(value);
			}
			if (encode) {
				temp.append(URLEncoder.encode(valueString, "UTF-8"));
			} else {
				temp.append(valueString);
			}
		}
//		System.out.println(temp.toString());
		return EncryptJAVAjs.createToken(temp.toString(), "MD5").toUpperCase();
	}

	/**
	 * SHA1加密
	 * @param input
	 * @return
	 * @throws NoSuchAlgorithmException
	 */
	public static String sha1(String input) throws NoSuchAlgorithmException {
		MessageDigest mDigest = MessageDigest.getInstance("SHA1");
		byte[] result = mDigest.digest(input.getBytes());
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < result.length; i++) {
			sb.append(Integer.toString((result[i] & 0xff) + 0x100, 16).substring(1));
		}
		return sb.toString();
	}

	//密钥 (需要前端和后端保持一致)
	private static String KEY = "wewqwewqewqewq"/*InitConst.TOKEN_KEY + InitConst.SIGN_KEY*/;
//	private static String IV = InitConst.TOKEN_KEY + InitConst.SIGN_KEY;
    //算法
    private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";
    
    /** 
     * aes加密  使用默认key
     * @param content 
     * @return 
     * @throws Exception 
     */  
    public static String encrypt(String content) {  
    	try {
    		return encrypt(content, KEY);
    	} catch (Exception e) {
    		e.printStackTrace();
    		return "";
    	}  
    }  
    
    /** 
     * aes解密 使用默认key
     * @param encrypt   内容 
     * @return 
     * @throws Exception 
     */  
    public static String desEncrypt(String encrypt) {  
        try {
            return desEncrypt(encrypt, KEY);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }  
    }  
    
	/**
	 * 根据token加密
	 * @param data
	 * @param token
	 * @return
	 * @throws Exception
	 */
	public static String encryptByToken(String data, String token) throws Exception {
		if(data==null||"".equals(data)) {
			return "";
		}
		return encrypt(data, token.substring(0, 16));
	}
	
	/**
	 * 根据token解密
	 * @param data
	 * @param token
	 * @return
	 * @throws Exception
	 */
	public static String desEncryptByToken(String data, String token) throws Exception {
		if(data==null||"".equals(data)) {
			return "";
		}
		return desEncrypt(data, token.substring(0, 16));
	}
    
    /** 
     * 指定密钥加密
     * AES加密为base 64 code
     * @param content 待加密的内容 
     * @param encryptKey 加密密钥 
     * @return 加密后的base 64 code 
     * @throws Exception 
     */  
    public static String encrypt(String content, String encryptKey) throws Exception {  
        return base64Encode(aesEncryptToBytes(content, encryptKey));  
    } 
  
    /** 
     * 指定密钥解密
     * 将base 64 code AES解密
     * @param encryptStr 待解密的base 64 code 
     * @param decryptKey 解密密钥 
     * @return 解密后的string 
     * @throws Exception 
     */  
    public static String desEncrypt(String encryptStr, String decryptKey) throws Exception {  
        return StringUtil.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);  
    } 
    
    /** 
     * base 64 encode 
     * @param bytes 待编码的byte[] 
     * @return 编码后的base 64 code 
     */  
    public static String base64Encode(byte[] bytes){  
        return Base64.encodeBase64String(bytes);  
    }  
  
    /** 
     * base 64 decode 
     * @param base64Code 待解码的base 64 code 
     * @return 解码后的byte[] 
     * @throws Exception 
     */  
    @SuppressWarnings("restriction")
	public static byte[] base64Decode(String base64Code) throws Exception{  
        return StringUtil.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);  
    }  
	
    /** 
     * AES加密 
     * @param content 待加密的内容 
     * @param encryptKey 加密密钥 
     * @return 加密后的byte[] 
     * @throws Exception 
     */  
    public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {  
        KeyGenerator kgen = KeyGenerator.getInstance("AES");  
        kgen.init(128);  
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);  
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));  
  
        return cipher.doFinal(content.getBytes("utf-8"));  
    }  
  
    /** 
     * AES解密 
     * @param encryptBytes 待解密的byte[] 
     * @param decryptKey 解密密钥 
     * @return 解密后的String 
     * @throws Exception 
     */  
    public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {  
        KeyGenerator kgen = KeyGenerator.getInstance("AES");  
        kgen.init(128);  
  
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);  
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));  
        byte[] decryptBytes = cipher.doFinal(encryptBytes);  
        return new String(decryptBytes);  
    }
	
    /** 
     * 将byte[]转为各种进制的字符串 
     * @param bytes byte[] 
     * @param radix 可以转换进制的范围，从Character.MIN_RADIX到Character.MAX_RADIX，超出范围后变为10进制 
     * @return 转换后的字符串 
     */  
    public static String binary(byte[] bytes, int radix){  
        return new BigInteger(1, bytes).toString(radix);// 这里的1代表正数  
    }  
	
	//TODO 生成唯一邀请码
	public static String createInviteCode(String id) {
		int a = 8-id.length();
		String code = "";
		if(a>0) {
			for (int i = 0; i < a; i++) {
				code += "0";
			}
			code += id;
		}
		return a>0?code:id;
	}

	/**
	 * 测试
	 */
	public static void main(String args[]) throws Exception {

/*		String phone = "18712334212";
		String token = createToken(phone);
		System.out.println(token);
		System.out.println(phone.substring(0, 3)+"****"+phone.substring(7, 11));*/
/*		String uri = "/tt/api/user/quit";
		Map<String ,String > map = Maps.newHashMap();
		map.put("uuid", "9LxUm12q");
		map.put("times", "1523963220");
		map.put("token", "4020ABCC6D5876768242860F9C9B847B");
		String sign = createSign(uri,map,true);
		System.out.println(sign);*/
//		System.out.println(createInviteCode("3"));
/*		String data = "1234567890 1";
		System.out.println(encrypt(data));;
		String desData = desEncrypt(encrypt(data));
		
		System.out.println(desData+"--");;
		
		System.out.println(desData.trim()); */
		System.out.println(encrypt("EWFSLIDHLShdifeoiikszdsa"));
	}
}
/*
*//**
 * 加密（需要先加载lib/aes/aes.min.js文件）
 * @param word
 * @returns {*}
 *//*
function encrypt(word){
    var key = CryptoJS.enc.Utf8.parse("abcdefgabcdefg12");
    var srcs = CryptoJS.enc.Utf8.parse(word);
    var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
    return encrypted.toString();
}

*//**
 * 解密
 * @param word
 * @returns {*}
 *//*
function decrypt(word){
    var key = CryptoJS.enc.Utf8.parse("abcdefgabcdefg12");
    var decrypt = CryptoJS.AES.decrypt(word, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});
    return CryptoJS.enc.Utf8.stringify(decrypt).toString();
}*/
